//: # 访问控制
// 访问控制可以限定其他源文件或模块中代码对你代码的访问级别。

import Foundation

//: 模块和源文件
//Swift中的访问控制模型基于模块和源文件这两个概念。
//模块：指的是以独立单元构建和发布的 Framework 或 Application。一个模块可以使用 import 关键字引入另外一个模块。
//源文件：指的是 Swift 中的 Swift File ，就是编写 Swift 源代码的文件，它通常属于一个模块。

//: 访问级别
/*
 • public: 可以访问自己模块中源文件里的任何实体，别人也可以通过引入该模块来访问源文件里的所有实体。通常情况下，Framework 中的某个接口是可以被任何人使用时，你可以将其设置为 public 级别。
 
 • internal: 可以访问自己模块中源文件里的任何实体，但是别人不能访问该模块中源文件里的实体。通常情况下，某个接口或 Framework 作为内部结构使用时，你可以将其设置为级别。
 
 • private: 只能在当前源文件中使用的实体，称为私有实体。使用级别，可以用作隐藏某些功能的实现细节。
*/

//Swift 中的访问级别遵循一个使用原则: 访问级别统一性。
/*
 • 一个 public 访问级别的变量，不能将它的类型定义为 internal 和 private
 • 函数的访问级别不能高于它的参数、返回类型的访问级别。
 */

//访问控制语法
public class SomePublicClass {}
internal class SomeInternalClass {}
private class SomePrivateClass {}

public var somePublicVariable = 0
internal let someInternalConstant = 0
private func somePrivateFunction() {}

//默认为 internal 级别
class SomeInternalClass1 {} // 隐式访问级别
internal var someInternalConstant1 = 0 //隐式访问级别 internal


//元组类型: 元组的访问级别与元组中访问级别最低的类型一致

//函数类型: 函数的访问级别需要根据该函数的参数类型和返回类型的访问级别得出

//枚举类型: 枚举中成员的访问级别继承自该枚举，你不能为枚举中的成员单独申明不同的访问级别。

//原始值和关联值: 枚举定义中的任何原始值或关联值的类型都必须有一个访问级别，这个级别至少要不低于枚举的访问级别。

//子类: 访问级别不得高于父类的访问级别

//常量、变量、属性、下标: 不能拥有比它们的类型更高的访问级别。

//初始化: 可以给自定义的初始化方法申明访问级别，但是要不高于它所属类的访问级别。但必要构造器例外，它的访问级别必须和所属类的访问级别相同。

//默认初始化方法: 访问级别与所属类型的访问级别相同

//结构体的默认成员初始化方法: 如果结构体中的任一存储属性的访问级别为 private ，那么它的默认成员初始化方法访问级别就是 private。尽管如此，结构体的初始化方法的访问级别依然是 internal。

//协议: 协议中的每一个必须要实现的函数都具有和该协议相同的访问级别。

//协议继承: 如果定义了一个新的协议，并且该协议继承了一个已知的协议，那么新协议拥有的访问级别最高也只和被继承协议的访问级别相同

//协议一致性: 类可以采用比自身访问级别低的协议。采用了协议的类的访问级别取它本身和所采用协议中最低的访问级别。

//扩展: 扩展成员应该具有和原始类成员一致的访问级别。

//协议的扩展: 如果一个扩展采用了某个协议，那么你就不能对该扩展使用访问级别修饰符来申明了。该扩展中实现协议的方法都会遵循该协议的访问级别。

//泛型: 泛型类型或泛型函数的访问级别取泛型类型、函数本身、泛型类型参数三者中的最低访问级别。

//类型别名: 任何你定义的类型别名都会被当作不同的类型，以便于进行访问控制。一个类型别名的访问级别不可高于原类型的访问级别。


